#include "app_bt.h"
#include "string.h"

/**
 *
  把字节数组转换为蓝牙数据
   * 准备向设备写前处理数据来满足蓝牙发送数据的要求
 * 当前data: conn_type id_len msg_len id msg (01 02 03 ff ff 11 22 33)
 * 蓝牙发送数据格式:  41 54 2b 4d 45 53 48 00 6f 6f 45 46 0d 0a
  示例：41 54 2b 4d 45 53 48 00 ff ff 41 42 43 0d 0a
        41 54 2b 4d 45 53 48 00： AT+MESH（固定头部）
        ff ff: 对端的MADDR（如果是FFFF代表群发）
        11 22 33: 要发送的数据（不超过12字节）
        0d 0a：\r\n（固定结尾）
*/

static char write_header[8] = {0x41, 0x54, 0x2b, 0x4d, 0x45, 0x53, 0x48, 0x00};
static char write_tailer[2] = {0x0d, 0x0a};

static int app_bt_pre_write(char *write_data, int write_data_len)
{
    // 1.提取id msg
    int id_len = write_data[1];
    int msg_len = write_data[2];
    char id[id_len];
    char msg[msg_len];
    memcpy(id, write_data + 3, id_len);
    memcpy(msg, write_data + 3 + id_len, msg_len);

    // 2.拼接数据
    memcpy(write_data, write_header, 8);                        // 帧头
    memcpy(write_data + 8, id, id_len);                         // id
    memcpy(write_data + 8 + id_len, msg, msg_len);              // msg
    memcpy(write_data + 8 + id_len + msg_len, write_tailer, 2); // 帧尾

    int data_len = 8 + id_len + msg_len + 2;
    return data_len;
}
/**
 *  读后预处理
 *
 * 读取蓝牙中的数据  转换为 字节数组
 *
 * 从设备读取数据后处理数据来满足网关应用的要求
 * 接收方得到数据1（4）：ok\r\n
 * 接收方得到数据2（3 + [2]）：f1 dd 07 23 23 ff ff 41 42 43
    f1 dd : 固定的头部
    07： 之后数据的长度（5-16之间）
    23 23：对端（发送方）的MADDR
    ff ff: 我的MADDR或ffff(群发)
    41 42 43：发送的数据
* 处理后的数据格式：conn_type id_len msg_len id msg
* 先准备一个buffer接收数据
* 1.读取数据先写入到buffer中
* 2.尝试判断是否是完整的数据
* 3.判断buffer中是否包含帧头数据
* 4.把帧头以前的数据全部清理，并且调整buffer的长度
* 5.在buffer中判断数据是否达到最小整帧数据(最短8字节)
* 6.提取数据的长度(第三个字节)，判断缓冲区是否有整帧数据
* 7.如果有整帧数据
* 7.1提取id和msg
* 7.2拼接为字节数组
* 7.3清理buffer中已经处理的数据，并将buffer的数据长度进行调整
* 8.返回数据的长度
*/

// 先准备一个buffer接收数据
static char temp_buffer[128] = {0};
static int data_len = 0;                   // 缓冲区数据长度
static char read_header[2] = {0xf1, 0xdd}; // 固定的头部

static void remove_data(int remove_len)
{
    memmove(temp_buffer, temp_buffer + remove_len, data_len - remove_len);
    data_len -= remove_len;
}
static int app_bt_post_read(char *read_data, int read_data_len)
{
    // * 1.读取数据先写入到buffer中
    memcpy(temp_buffer + data_len, read_data, read_data_len);
    data_len += read_data_len;
    // * 2.尝试判断是否是完整的数据
    // * 3.判断buffer中是否包含帧头数据
    for (size_t i = 0; i < data_len - 1; i++)
    {
        if (temp_buffer[i] == read_header[0] && temp_buffer[i + 1] == read_header[1])
        {
            // 说明找到帧头数据
            //  * 4.把帧头以前的数据全部清理，并且调整buffer的长度
            remove_data(i);
            // * 5.在buffer中判断数据是否达到最小整帧数据(最短8字节)
            if (data_len < 8)
            {
                return 0;
            }
            // * 6.提取数据的长度(第三个字节)，判断缓冲区是否有整帧数据
            int real_data_len = temp_buffer[2] + 3;
            if (data_len < real_data_len)
            {
                return 0;
            }
            // * 7.如果有整帧数据
            // * 7.1提取id和msg
            int id_len = 2;                  // 蓝牙的id长度是固定的
            int msg_len = real_data_len - 7; // 7 = 帧头(2) + 长度(1) + 对端id长度(2) +本端id长度(2)
            char id[2];
            char msg[msg_len];
            memcpy(id, temp_buffer + 5, id_len);
            memcpy(msg, temp_buffer + 7, msg_len);
            // * 7.2拼接为字节数组
            read_data[0] = conn_type_ble;                 // 蓝牙连接
            read_data[1] = id_len;                        // id长度
            read_data[2] = msg_len;                       // msg长度
            memcpy(read_data + 3, id, id_len);            // id
            memcpy(read_data + 3 + id_len, msg, msg_len); // msg

            // * 7.3清理buffer中已经处理的数据，并将buffer的数据长度进行调整
            remove_data(real_data_len);

            // * 8.返回数据的长度
            int final_data_len = 3 + id_len + msg_len;
            return final_data_len;
        }
    }
    return 0;
}

/**
 *@brief 为设备进行蓝牙的初始化
 *1.对蓝牙模块进行初始化(eg:网段，地址，波特率....)
 *2.设置蓝牙数据的预处理方法
 *2.1写前预处理
 *2.2读后预处理
 */
int app_bt_init(app_device_t *device)
{
    device->pre_write = app_bt_pre_write;
    device->post_read = app_bt_post_read;
    return 0;
}